﻿using AntMovement.Core;
using AntMovement.Core.IParameter;
using AntMovement.Core.Model;
using AntMovement.Menu.HardControl.Model;
using AntMovement.Parameter;
using AntMovement.Parameter.Model;
using AntMovement.WPF.Resources.Controls;
using Prism.Commands;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace AntMovement.Menu.HardControl.ViewModels
{
    public class AxisHomeViewModel : IViewModelLife
    {
        public AsyncObservableCollection<LogInfoModel> LogList { get; set; }
        public ObservableCollection<AxisInfoModel> AxisInfos { get; set; }
        
        public TemporaryParameter TP { get; set; }
        private TemporaryParameter _temporary;
        public IOParameter IOP { get; set; }
        public AxisParameter AxisPara { get; set; }
        private CancellationTokenSource _tokenSource;
        public List<string> AxisNameItems { get; set; }
        private HoldParameter _hold;
        private IDialogHost _dialogHost;
        public AxisHomeViewModel(IAxisParameter axisParameter, ITemporaryParameter temporaryParameter, ILog log, IIOParameter iOParameter, IHoldParameter hold, IDialogHost dialogHost)
        {
            IOP = (IOParameter)iOParameter;
            LogList = (AsyncObservableCollection<LogInfoModel>)log.GetInfo();
            AxisPara = (AxisParameter)axisParameter;
            _tokenSource = new CancellationTokenSource();
            AxisInfos = new ObservableCollection<AxisInfoModel>();
            AxisNameItems = new List<string>();
            foreach (var item in AxisPara.AxisDataSet)
            {
                AxisInfos.Add(new AxisInfoModel()
                {
                    AxisID = item.AxisID,
                    SportStatus = item.Status.SportStatus,
                    Name = item.Name,
                });
            }
            foreach (var item in AxisPara.AxisDataSet)
            {
                if (item.Name.Contains("轴"))
                {
                    AxisNameItems.Add(item.Name);
                }
            }
            _temporary = (TemporaryParameter)temporaryParameter;
            TP = _temporary;
            ThreadPool.QueueUserWorkItem(new WaitCallback(sender =>
            {
                while (!_tokenSource.Token.IsCancellationRequested)
                {
                    for (int i = 0; i < AxisPara.AxisDataSet.Count; i++)
                    {
                        AxisInfos[i].CurrentPostion = AxisPara.AxisDataSet[i].Status.CurrentPostion;
                        AxisInfos[i].ORG = AxisPara.AxisDataSet[i].Status.ORG;
                        AxisInfos[i].SportStatus = AxisPara.AxisDataSet[i].Status.SportStatus;
                        AxisInfos[i].EMG = AxisPara.AxisDataSet[i].Status.EMG;
                        AxisInfos[i].El_Left = AxisPara.AxisDataSet[i].Status.El_Left;
                        AxisInfos[i].El_Right = AxisPara.AxisDataSet[i].Status.El_Right;
                        AxisInfos[i].CurrentSpeed = AxisPara.AxisDataSet[i].Status.CurrentSpeed;
                        AxisInfos[i].ActualPosition = AxisPara.AxisDataSet[i].UnitConversion.ActualPosition;
                        AxisInfos[i].INP = AxisPara.AxisDataSet[i].Status.INP;
                        AxisInfos[i].Enable = AxisPara.AxisDataSet[i].Status.Enable;
                        AxisInfos[i].IsHome = AxisPara.AxisDataSet[i].Status.IsHome;
                        AxisInfos[i].EqPostion = AxisPara.AxisDataSet[i].Status.EqPostion;
                    }
                    Thread.Sleep(80);
                }
            }));
            _hold = (HoldParameter)hold;
            _dialogHost = dialogHost;
        }

        public Prism.Commands.DelegateCommand<string> MouseLeftButton => new Prism.Commands.DelegateCommand<string>(sender => _temporary.OneKeyHome = sender == "Down");

        public Prism.Commands.DelegateCommand<string> SelectionMove => new Prism.Commands.DelegateCommand<string>(sender =>
        {
            if (!_temporary.JogMove)
            {
                _temporary.JogName = sender;
                _temporary.JogMove = true;
            }
        });

        #region 反方向
        public Prism.Commands.DelegateCommand<string> ReverseMovePutUp => new Prism.Commands.DelegateCommand<string>(sender =>
        {
            if (string.IsNullOrEmpty(sender) || _temporary.SystemStatus.Auto)
            {
                return;
            }
            _temporary.JogName = sender;
            _temporary.JogDown = false;
        });

        public Prism.Commands.DelegateCommand<string> ReverseMovePress => new Prism.Commands.DelegateCommand<string>(sender =>
        {
            if (string.IsNullOrEmpty(sender) || _temporary.SystemStatus.Auto)
            {
                return;
            }
            _temporary.JogName = sender;
            _temporary.JogDown = true;
        });
        #endregion

        #region 正方向
        public Prism.Commands.DelegateCommand<string> ForwardMovePutUp => new Prism.Commands.DelegateCommand<string>(sender =>
        {
            if (string.IsNullOrEmpty(sender) || _temporary.SystemStatus.Auto)
            {
                return;
            }
            _temporary.JogName = sender;
            _temporary.JogUp = false;
        });

        public Prism.Commands.DelegateCommand<string> ForwardMovePress => new Prism.Commands.DelegateCommand<string>(sender =>
        {
            if (string.IsNullOrEmpty(sender) || _temporary.SystemStatus.Auto)
            {
                return;
            }
            _temporary.JogName = sender;
            _temporary.JogUp = true;
        });
        #endregion

        public DelegateCommand<CheckBox> ServoChecked => new DelegateCommand<CheckBox>(sender =>
        {
            if (!_temporary.SystemStatus.ManualOperation)
            {
                return;
            }
            if (string.IsNullOrEmpty(_temporary.ServoName))
            {
                _temporary.ServoEnable = (bool)sender.IsChecked;
                _temporary.ServoName = sender.ToolTip.ToString();
            }
        });

        public DelegateCommand<string> SelectionHome => new DelegateCommand<string>(sender =>
        {
            if (!_temporary.SystemStatus.ManualOperation) return;
            if (!_temporary.AxisHome)
            {
                _temporary.AxisNameHome = sender;
                _temporary.AxisHome = !_temporary.AxisHome;
            }
        });

        public Prism.Commands.DelegateCommand<string> SelectionTeach => new Prism.Commands.DelegateCommand<string>(sender =>
        {
            if (!_temporary.SystemStatus.ManualOperation) return;
            var model = AxisPara.PointPosition.FirstOrDefault(x => x.Name == sender);
            if (model != null)
            {
                var x = AxisPara.AxisDataSet.FirstOrDefault(x => x.Name == "X轴");
                var y = AxisPara.AxisDataSet.FirstOrDefault(x => x.Name == "Y轴");
                var z = AxisPara.AxisDataSet.FirstOrDefault(x => x.Name == "Z轴");
                var r = AxisPara.AxisDataSet.FirstOrDefault(x => x.Name == "R轴");
                model.XPulse = x.Status.CurrentPostion;
                model.YPulse = y.Status.CurrentPostion;
                model.ZPulse = z?.Status.CurrentPostion ?? 0;
                model.RPulse = r?.Status.CurrentPostion ?? 0;
                if (sender == "码垛1终点位")
                {
                    var startModel = AxisPara.PointPosition.FirstOrDefault(x => x.Name == "码垛1起点位");
                    if (startModel != null)
                    {
                        _hold.MaterialSpacingLine = Math.Abs(Math.Round((x.UnitConversion.ActualPosition - PulseToDistance(startModel.XPulse, x)) / (double)(_hold.XCount - 1), 2, MidpointRounding.AwayFromZero));
                        _hold.MaterialSpacingColumn = Math.Abs(Math.Round((y.UnitConversion.ActualPosition - PulseToDistance(startModel.YPulse, y)) / (double)(_hold.YCount - 1), 2, MidpointRounding.AwayFromZero));
                    }
                }
                AxisPara.Save();
            }
        });

        public DelegateCommand StartMonocycle => new DelegateCommand(() =>
        {
            if (!_temporary.SystemStatus.ManualOperation) return;
            if (!_temporary.Monocycle)
            {
                _temporary.Monocycle = true;
            }
        });

        public DelegateCommand Move => new DelegateCommand(() =>
        {
            if (_temporary.SystemStatus.ManualOperation && !TP.FixedPointMove)
            {
                TP.FixedPointMove = true;
            }
        });

        public DelegateCommand<string> StartCalibration => new DelegateCommand<string>(async sender =>
        {
            if (!_temporary.SystemStatus.ManualOperation)
            {
                return;
            }
            var result = await _dialogHost.DialogShow($"二次确认是否需要进行[{sender}#吸嘴]标定", Core.Enum.LogLevel.Warning, hostDialog: Core.Enum.PopUpType.Global, dialogShowButton: Core.Enum.DialogShowButton.YesNo);
            if (result.ToString().ToUpper() == "YES")
            {
                if (!_temporary.Calibration)
                {
                    _temporary.Calibration = true;
                    _temporary.CalibrationIndex = Convert.ToInt32(sender);
                }
            }
        });

        public DelegateCommand StartOrientation => new DelegateCommand(() =>
        {
            if (!_temporary.SystemStatus.ManualOperation)
            {
                return;
            }
            if (!_temporary.Orientation)
            {
                _temporary.Orientation = true;
            }
        });

        public void Enter()
        {

        }

        public void Exit()
        {
            _tokenSource.Cancel();
        }

        #region 行程与脉冲转换
        private double PulseToDistance(Core.Entity.Axis axis) => Math.Round(GetPE(axis) * (double)axis.Status.CurrentPostion, 6, MidpointRounding.AwayFromZero);
        private double PulseToDistance(long pulse, Core.Entity.Axis axis) => Math.Round(GetPE(axis) * (double)pulse, 6, MidpointRounding.AwayFromZero);

        private long DistanceToPulse(double distance, Core.Entity.Axis axis) => (long)Math.Round(distance / GetPE(axis), 6, MidpointRounding.AwayFromZero);

        private double GetPE(Core.Entity.Axis axis)
        {
            double pe = 0;
            if (axis.UnitConversion.EnableGearbox)
            {
                if (axis.UnitConversion.EnableRotationMode)
                {
                    //旋转模式

                }
                else
                {
                    //线性模式
                    pe = (axis.UnitConversion.WeeklyItinerary * axis.UnitConversion.MotorGearRatio) / (axis.UnitConversion.CyclePulse * axis.UnitConversion.WorkingGearRatio);
                }
            }
            else
            {
                pe = axis.UnitConversion.WeeklyItinerary / axis.UnitConversion.CyclePulse;
            }
            return pe;
        }
        #endregion
    }
}
